#include "InterpolateLinear.h"

QRgb InterpolateLinear::interpolate (const QImage& src, const QPointF& p)
{
  int w = src.width ();
  int h = src.height ();
  if (p.x () < 0 || p.x () > w - 1 || p.y () < 0 || p.y () > h - 1)
    return 0;
  int bytesPerPixel = src.depth () / 8;
  if (p.x () == w - 1 || p.y () == h - 1) {
	  switch (bytesPerPixel) {
	  case 4:
		  return ((int*)src.scanLine (p.y ()))[(int)p.x ()];
	  case 2:
		  return ((unsigned short*)src.scanLine (p.y ()))[(int)p.x ()];
	  case 1:
		  return src.scanLine (p.y ())[(int)p.x ()];
	  default:
		  throw ("Unsupport format.");
	  }
  }

  QPoint p0 ((int)p.x (), (int)p.y ());
  QPoint p1 ((int)p.x () + 1, (int)p.y ());
  QPoint p2 ((int)p.x () + 1, (int)p.y () + 1);
  QPoint p3 ((int)p.x (), (int)p.y () + 1);

  __int32 colorRet;
  
  int rgb0, rgb1, rgb2, rgb3;
  switch (bytesPerPixel) {
  case 4:
	  rgb0 = ((int*)src.scanLine (p0.y ()))[p0.x ()];
	  rgb1 = ((int*)src.scanLine (p1.y ()))[p1.x ()];
	  rgb2 = ((int*)src.scanLine (p2.y ()))[p2.x ()];
	  rgb3 = ((int*)src.scanLine (p3.y ()))[p3.x ()];
	  for (int i = 0; i < bytesPerPixel; ++i)
	  {
		  uchar c0 = ((uchar *)&(rgb0))[i];
		  uchar c1 = ((uchar *)&(rgb1))[i];
		  uchar c2 = ((uchar *)&(rgb2))[i];
		  uchar c3 = ((uchar *)&(rgb3))[i];
		  uchar t0 = ((float)(c1 - c0)) * (p.x () - p0.x ()) + c0;
		  uchar t1 = ((float)(c2 - c3)) * (p.x () - p0.x ()) + c3;
		  ((uchar*)&colorRet)[i] = ((float)(t1 - t0)) * (p.y () - p0.y ()) + t0;
	  }
	  break;
  case 2:
	  rgb0 = ((unsigned short*)src.scanLine (p0.y ()))[p0.x ()];
	  rgb1 = ((unsigned short*)src.scanLine (p1.y ()))[p1.x ()];
	  rgb2 = ((unsigned short*)src.scanLine (p2.y ()))[p2.x ()];
	  rgb3 = ((unsigned short*)src.scanLine (p3.y ()))[p3.x ()];
	  {
		  int t0 = ((float)(rgb1 - rgb0)) * (p.x () - p0.x ()) + rgb0;
		  int t1 = ((float)(rgb2 - rgb3)) * (p.x () - p0.x ()) + rgb3;
		  colorRet = ((float)(t1 - t0)) * (p.y () - p0.y ()) + t0;
	  }
	  break;
  case 1:
	  rgb0 = src.scanLine (p0.y ())[p0.x ()];
	  rgb1 = src.scanLine (p1.y ())[p1.x ()];
	  rgb2 = src.scanLine (p2.y ())[p2.x ()];
	  rgb3 = src.scanLine (p3.y ())[p3.x ()];
	  {
		  int t0 = ((float)(rgb1 - rgb0)) * (p.x () - p0.x ()) + rgb0;
		  int t1 = ((float)(rgb2 - rgb3)) * (p.x () - p0.x ()) + rgb3;
		  colorRet = ((float)(t1 - t0)) * (p.y () - p0.y ()) + t0;
	  }
	  break;
  default:
	  throw ("Unsupport format.");
  }
  return colorRet;
}
